package com.xxl.job.core.thread;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ExecutorBuilder;
import cn.hutool.core.thread.ThreadUtil;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.xxl.job.core.log.XxlJobFileAppender;
import com.xxl.job.core.util.ExecutorHelper;
import com.xxl.job.core.util.FileUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.*;

/**
 * job file clean thread
 *
 * @author xuxueli 2017-12-29 16:23:43
 */
public class JobLogFileCleanThread {
    private static final Logger logger = LoggerFactory.getLogger(JobLogFileCleanThread.class);

    public static JobLogFileCleanThread getInstance() {
        return JobLogFileCleanThreadHolder.INSTANCE;
    }

    private static class JobLogFileCleanThreadHolder {
        private static final JobLogFileCleanThread INSTANCE = new JobLogFileCleanThread();
    }
    private ExecutorService executorService;
    private volatile boolean toStop = false;

    public void start(final long logRetentionDays) {

        // limit min value
        if (logRetentionDays < 3) {
            return;
        }
        executorService = ExecutorHelper.getInstance().createSingleExecutor("xxl-job, executor JobLogFileCleanThread");
        executorService.execute(() -> {
            while (!toStop) {
                try {
                    // clean log dir, over logRetentionDays
                    File[] childDirs = new File(XxlJobFileAppender.getLogPath()).listFiles();
                    if (childDirs != null && childDirs.length > 0) {

                        // today
                        Calendar todayCal = Calendar.getInstance();
                        todayCal.set(Calendar.HOUR_OF_DAY, 0);
                        todayCal.set(Calendar.MINUTE, 0);
                        todayCal.set(Calendar.SECOND, 0);
                        todayCal.set(Calendar.MILLISECOND, 0);

                        Date todayDate = todayCal.getTime();

                        for (File childFile : childDirs) {

                            // valid
                            if (!childFile.isDirectory()) {
                                continue;
                            }
                            if (!childFile.getName().contains("-")) {
                                continue;
                            }

                            // file create date
                            Date logFileCreateDate = DateUtil.parse(childFile.getName(), "yyyy-MM-dd");

                            if ((todayDate.getTime() - logFileCreateDate.getTime()) >= logRetentionDays * (24 * 60 * 60 * 1000)) {
                                FileUtil.deleteRecursively(childFile);
                            }
                        }
                    }
                } catch (Exception e) {
                    if (!toStop) {
                        logger.error(e.getMessage(), e);
                    }
                }

                try {
                    TimeUnit.DAYS.sleep(1);
                } catch (InterruptedException e) {
                    if (!toStop) {
                        logger.error(e.getMessage(), e);
                    }
                }
            }
            logger.info(">>>>>>>>>>> xxl-job, executor JobLogFileCleanThread thread destroy.");

        });
    }

    public void toStop() {
        toStop = true;
        ExecutorHelper.getInstance().shutdown(executorService);
    }

}
